﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace INIGui
{
    public partial class frmIniWindow : Form
    {

        private bool _modified;
        private string _lastLocation;
        private IniLibrary.INI _ini = new IniLibrary.INI();
        private enum ContextOption
        {
            AddSection,
            EditSection,
            RemoveSection,
            AddKey,
            EditKey,
            RemoveKey
        }

        public void Save()
        {
            if (string.IsNullOrEmpty(_lastLocation))
            {
                using (var sfd = new SaveFileDialog() { Title = Properties.Resources.sfdTitle, Filter = Properties.Resources.ofdFilter })
                {
                    if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        _lastLocation = sfd.FileName;
                    else
                        return;
                }
            }
            _ini.Save(_lastLocation, IniLibrary.INI.Type.INI);
            this.Text = string.Format("INI Editor - {0}", System.IO.Path.GetFileNameWithoutExtension(_lastLocation));
            _modified = false;
        }
        public void Save(string filepath)
        {
            _lastLocation = filepath;
            Save();
        }
        public void Open(string filepath)
        {
            _ini.Load(filepath, IniLibrary.INI.Type.INI);
            _lastLocation = filepath;
            this.Text = string.Format("INI Editor - {0}", System.IO.Path.GetFileNameWithoutExtension(_lastLocation));
            BuildTreeView(false);
        }
        public void Merge(string filepath)
        {
            _ini.Merge(filepath, IniLibrary.INI.Type.INI);
            BuildTreeView();
        }

        public frmIniWindow()
        {
            InitializeComponent();
        }

        private void frmIniWindow_Load(object sender, EventArgs e)
        {

            // disable everything but the Add Section option.
            ContextEditor(ContextOption.AddKey, false);
            ContextEditor(ContextOption.AddSection, true);
            ContextEditor(ContextOption.EditKey, false);
            ContextEditor(ContextOption.EditSection, false);
            ContextEditor(ContextOption.RemoveKey, false);
            ContextEditor(ContextOption.RemoveSection, false);

            // build the view.
            BuildTreeView(false);

        }

        private void addSectionToolStripMenuItem_Click(object sender, EventArgs e)
        {

            // create a new add section option
            var sectionWindow = new Dialogs.DialogAddSection();

            // now show it
            if (sectionWindow.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _ini.Add(sectionWindow.SectionName);
                BuildTreeView();
            }

        }

        private void editSectionToolStripMenuItem_Click(object sender, EventArgs e)
        {

            var currentNode = tvIniFile.SelectedNode;
            var editSection = new Dialogs.DialogEditSection();
            IniLibrary.INI.Section currentSection;

            if (currentNode.Parent == null)
            {
                // we can assume that this is a section node of some sort.
                currentSection = currentNode.Tag as IniLibrary.INI.Section;
            }
            else
            {
                // this might be a key of some sort.
                currentSection = currentNode.Parent.Tag as IniLibrary.INI.Section;
            }

            // window
            if (editSection.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                currentSection.Name = editSection.SectionName;
                BuildTreeView();
            }
            
        }

        private void removeSectionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            
            // let's try and figure out where we are.
            var currentNode = tvIniFile.SelectedNode;
            var sectionName = string.Empty;

            // Do we have a parent?
            if (currentNode.Parent == null)
                sectionName = (currentNode.Tag as IniLibrary.INI.Section).Name;
            else
                sectionName = (currentNode.Parent.Tag as IniLibrary.INI.Section).Name;

            // ask
            if (MessageBox.Show(string.Format("Are you sure you want to remove section '{0}' from the INI file?", sectionName), "Remove section?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                _ini.Remove(sectionName);
                BuildTreeView();
            }


        }

        private void addKeyToolStripMenuItem_Click(object sender, EventArgs e)
        {

            // let's try and figure out where we are.
            var currentNode = tvIniFile.SelectedNode;
            var keyDialog = new Dialogs.DialogAddEditKey();
            IniLibrary.INI.Section section;

            // Do we have a parent?
            if (currentNode.Parent == null)
                section = (currentNode.Tag as IniLibrary.INI.Section);
            else
                section = (currentNode.Parent.Tag as IniLibrary.INI.Section);

            // We need to add a key to this section.
            if (keyDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                section.Add(new IniLibrary.INI.Key { Name = keyDialog.KeyName, Value = keyDialog.KeyValue });
                BuildTreeView();
            }

        }

        private void editKeyToolStripMenuItem_Click(object sender, EventArgs e)
        {

            // get our current key.
            var currentNode = tvIniFile.SelectedNode;
            var currentKey = currentNode.Tag as IniLibrary.INI.Key;
            var keyDialog = new Dialogs.DialogAddEditKey() { KeyName = currentKey.Name, KeyValue = currentKey.Value.ToString() };

            // Check
            if (keyDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                currentKey.Name = keyDialog.KeyName;
                currentKey.Value = keyDialog.KeyValue;
                BuildTreeView();
            }

        }

        private void removeKeyToolStripMenuItem_Click(object sender, EventArgs e)
        {

            // get our current key.
            var currentNode = tvIniFile.SelectedNode;
            var currentKey = currentNode.Tag as IniLibrary.INI.Key;

            // get our section
            var currentSection = currentNode.Parent.Tag as IniLibrary.INI.Section;

            // build the question
            if (MessageBox.Show(string.Format("Are you sure you want to remove key '{0}' from the INI file?", currentKey.Name), "Remove key?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                _ini.Remove(currentSection.Name, currentKey.Name);
                BuildTreeView();
            }

        }

        private void tvIniFile_MouseDown(object sender, MouseEventArgs e)
        {
            //if (e.Button != System.Windows.Forms.MouseButtons.Right)
            {

                // get the nearest node
                var node = tvIniFile.GetNodeAt(e.X, e.Y);

                // now check if it's null
                if (node != null)
                { tvIniFile.SelectedNode = node; ContextParse(node); }

            }
        }


        /// <summary>
        /// Builds the TreeView.
        /// </summary>
        private void BuildTreeView(bool modified = true)
        {

            // check
            if (modified)
            {
                if (!Text.EndsWith("*"))
                    Text += "*";
                _modified = true;
            }

            // clear the treeview
            tvIniFile.Nodes.Clear();

            // reset all options
            ContextEditor(ContextOption.AddKey, false);
            ContextEditor(ContextOption.AddSection, true);
            ContextEditor(ContextOption.EditKey, false);
            ContextEditor(ContextOption.EditSection, false);
            ContextEditor(ContextOption.RemoveKey, false);
            ContextEditor(ContextOption.RemoveSection, false);

            // check
            if (_ini.Any())
            {
                // loop
                foreach (var section in _ini)
                {

                    // okay, create the node.
                    var sectionNode = new TreeNode();
                    sectionNode.Text = string.Format("{0} - {1} Keys", section.Name, section.Count());
                    sectionNode.Tag = section;

                    // now check
                    if (section.Any())
                    {
                        // add the nodes.
                        foreach (var key in section)
                        {
                            var keyNode = new TreeNode();
                            keyNode.Text = string.Format("{0} - {1}", key.Name, key.Value.ToString());
                            keyNode.Tag = key;
                            sectionNode.Nodes.Add(keyNode);
                        }
                    }
                    else
                    {
                        // no keys.
                        sectionNode.Nodes.Add("No keys in this section. Right click here to add keys to this section.");
                    }

                    // Add the section
                    tvIniFile.Nodes.Add(sectionNode);
                }
            }
            else
            {
                // no sections
                tvIniFile.Nodes.Add("No sections in this INI file. Right click here to add a section to this file.");
            }
        }

        /// <summary>
        /// Determines which ContextMenuStrip item is currently active based on the current node.
        /// </summary>
        /// <param name="currentNode">The currently selected node.</param>
        private void ContextParse(TreeNode currentNode)
        {
            // check the tag
            if (currentNode.Parent == null)
            {

                // Since the parent -is- null. We can for sure add a section.
                // ContextEditor(ContextOption.AddSection, true);
                // ^ That should never be disabled -anyway-.

                // Let's check to see if we can edit
                ContextEditor(ContextOption.EditSection, currentNode.Tag != null);
                ContextEditor(ContextOption.RemoveSection, currentNode.Tag != null);
                ContextEditor(ContextOption.AddKey, currentNode.Tag != null);


            }
            else
            {

                // okay, so the parent is not null, that means we -are- in a section node.
                // so we need to enable editing and removal of the section.
                ContextEditor(ContextOption.EditSection, true);
                ContextEditor(ContextOption.RemoveSection, true);

                // We can also add a key.
                ContextEditor(ContextOption.AddKey, true);

                // Now, check about the current tag.
                ContextEditor(ContextOption.EditKey, currentNode.Tag != null);
                ContextEditor(ContextOption.RemoveKey, currentNode.Tag != null);

            }
        }

        /// <summary>
        /// Enables and disables the various ContextMenuStrip items.
        /// </summary>
        /// <param name="option">The current item.</param>
        /// <param name="enabled">Enable/Disable</param>
        private void ContextEditor(ContextOption option, bool enabled)
        {
            switch (option)
            {
                case ContextOption.AddSection:
                    addSectionToolStripMenuItem.Enabled = enabled;
                    break;
                case ContextOption.EditSection:
                    editSectionToolStripMenuItem.Enabled = enabled;
                    break;
                case ContextOption.RemoveSection:
                    removeSectionToolStripMenuItem.Enabled = enabled;
                    break;
                case ContextOption.AddKey:
                    addKeyToolStripMenuItem.Enabled = enabled;
                    break;
                case ContextOption.EditKey:
                    editKeyToolStripMenuItem.Enabled = enabled;
                    break;
                case ContextOption.RemoveKey:
                    removeKeyToolStripMenuItem.Enabled = enabled;
                    break;
            }
        }

        private void frmIniWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_modified)
            {
                var result = MessageBox.Show(string.Format("Do you want to save your changes to {0}?", string.IsNullOrEmpty(_lastLocation) ? "Untitled" : System.IO.Path.GetFileNameWithoutExtension(_lastLocation)), "Save?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

                switch (result)
                {
                    case System.Windows.Forms.DialogResult.Yes:
                        Save();
                        _modified = false;
                        break;
                    case System.Windows.Forms.DialogResult.Cancel:
                        e.Cancel = true;
                        break;
                }
            }
        }
    }
}
